package org.jmap.core;

import org.osgeo.proj4j.CoordinateReferenceSystem;
import org.osgeo.proj4j.CoordinateTransform;
import org.osgeo.proj4j.CoordinateTransformFactory;
import org.osgeo.proj4j.ProjCoordinate;

public class MapPoint {

	public double lon = 0.0;
	public double lat = 0.0;
	
	public MapPoint(double lon, double lat) {
		this.lon = lon;
		this.lat = lat;
	}

	@Override
	public String toString() {
		return "MapPoint [lon=" + lon + ", lat=" + lat + "]";
	}
	
	public String toShortString() {
		return "[" + lon + ", " + lat + "]";
	}
	
	public MapPoint clone() {
		return new MapPoint(this.lon, this.lat);
	}
	
	public MapPoint add(double lon, double lat) {
		return new MapPoint(lon + this.lon, lat + this.lat);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		long temp;
		temp = Double.doubleToLongBits(lat);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = Double.doubleToLongBits(lon);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MapPoint other = (MapPoint) obj;
		if (Double.doubleToLongBits(lat) != Double.doubleToLongBits(other.lat))
			return false;
		if (Double.doubleToLongBits(lon) != Double.doubleToLongBits(other.lon))
			return false;
		return true;
	}
	
	
	public MapPoint transform(CoordinateReferenceSystem source, CoordinateReferenceSystem dest) {
		CoordinateTransformFactory transformFactory = new CoordinateTransformFactory();
		CoordinateTransform transform = transformFactory.createTransform(source, dest);
		
		ProjCoordinate transformed = new ProjCoordinate();
		
		transformed = transform.transform(new ProjCoordinate(this.lon, this.lat), transformed);
		
		this.lon = transformed.x;
		this.lat = transformed.y;
		
		return this;
	}
	
	public MapPoint wrapDateLine(Extent maxExtent) {
        MapPoint newPoint = this.clone();
        
        if (maxExtent != null) {
            //shift right
            while (newPoint.lon < maxExtent.left) {
                newPoint.lon +=  maxExtent.getWidth();
            }
           
            //shift left
            while (newPoint.lon > maxExtent.right) {
                newPoint.lon -= maxExtent.getWidth();
            }    
        }
                
        return newPoint;
	}
	
}
